/**
    @author: dt
    @date: 2025-06-23
    @description: 行为树黑板系统
*/

using System;
using System.Collections.Generic;
using UnityEngine;

namespace DLib.BehaviorTree
{
    /// <summary>
    /// 行为树黑板
    /// 用于在行为树节点之间共享数据
    /// 支持类型安全的数据存储和访问
    /// </summary>
    public class Blackboard
    {
        /// <summary>存储的数据字典</summary>
        private Dictionary<string, object> data = new Dictionary<string, object>();
        
        /// <summary>数据类型信息</summary>
        private Dictionary<string, Type> dataTypes = new Dictionary<string, Type>();
        
        /// <summary>数据变化事件</summary>
        private Dictionary<string, Action<object>> changeEvents = new Dictionary<string, Action<object>>();

        /// <summary>
        /// 设置黑板数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">数据键</param>
        /// <param name="value">数据值</param>
        public void SetValue<T>(string key, T value)
        {
            if (string.IsNullOrEmpty(key))
            {
                Debug.LogError("Blackboard: Key cannot be null or empty");
                return;
            }

            // 检查类型是否匹配
            if (dataTypes.ContainsKey(key) && dataTypes[key] != typeof(T))
            {
                Debug.LogError($"Blackboard: Type mismatch for key '{key}'. Expected {dataTypes[key]}, got {typeof(T)}");
                return;
            }

            // 检查值是否真的改变了
            if (data.ContainsKey(key) && Equals(data[key], value))
            {
                return; // 值没有改变，不触发事件
            }

            // 存储数据和类型信息
            data[key] = value;
            dataTypes[key] = typeof(T);

            // 触发变化事件
            if (changeEvents.ContainsKey(key))
            {
                changeEvents[key]?.Invoke(value);
            }

            Debug.Log($"Blackboard: Set '{key}' = {value} (Type: {typeof(T).Name})");
        }

        /// <summary>
        /// 获取黑板数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="key">数据键</param>
        /// <param name="defaultValue">默认值（如果键不存在）</param>
        /// <returns>数据值</returns>
        public T GetValue<T>(string key, T defaultValue = default(T))
        {
            if (string.IsNullOrEmpty(key))
            {
                Debug.LogError("Blackboard: Key cannot be null or empty");
                return defaultValue;
            }

            if (!data.ContainsKey(key))
            {
                Debug.LogWarning($"Blackboard: Key '{key}' not found, returning default value");
                return defaultValue;
            }

            // 检查类型是否匹配
            if (dataTypes[key] != typeof(T))
            {
                Debug.LogError($"Blackboard: Type mismatch for key '{key}'. Expected {typeof(T)}, got {dataTypes[key]}");
                return defaultValue;
            }

            return (T)data[key];
        }

        /// <summary>
        /// 检查黑板是否包含指定键
        /// </summary>
        /// <param name="key">数据键</param>
        /// <returns>是否包含该键</returns>
        public bool HasKey(string key)
        {
            return data.ContainsKey(key);
        }

        /// <summary>
        /// 删除黑板数据
        /// </summary>
        /// <param name="key">数据键</param>
        public void RemoveValue(string key)
        {
            if (data.ContainsKey(key))
            {
                data.Remove(key);
                dataTypes.Remove(key);
                changeEvents.Remove(key);
                Debug.Log($"Blackboard: Removed key '{key}'");
            }
        }

        /// <summary>
        /// 清空所有黑板数据
        /// </summary>
        public void Clear()
        {
            data.Clear();
            dataTypes.Clear();
            changeEvents.Clear();
            Debug.Log("Blackboard: Cleared all data");
        }

        /// <summary>
        /// 注册数据变化事件
        /// </summary>
        /// <param name="key">数据键</param>
        /// <param name="callback">回调函数</param>
        public void RegisterChangeEvent(string key, Action<object> callback)
        {
            if (!changeEvents.ContainsKey(key))
            {
                changeEvents[key] = null;
            }
            changeEvents[key] += callback;
        }

        /// <summary>
        /// 注销数据变化事件
        /// </summary>
        /// <param name="key">数据键</param>
        /// <param name="callback">回调函数</param>
        public void UnregisterChangeEvent(string key, Action<object> callback)
        {
            if (changeEvents.ContainsKey(key))
            {
                changeEvents[key] -= callback;
            }
        }

        /// <summary>
        /// 获取所有键
        /// </summary>
        /// <returns>所有键的集合</returns>
        public IEnumerable<string> GetAllKeys()
        {
            return data.Keys;
        }

        /// <summary>
        /// 获取数据类型
        /// </summary>
        /// <param name="key">数据键</param>
        /// <returns>数据类型</returns>
        public Type GetDataType(string key)
        {
            return dataTypes.ContainsKey(key) ? dataTypes[key] : null;
        }

        /// <summary>
        /// 获取黑板中键的数量
        /// </summary>
        /// <returns>键的数量</returns>
        public int GetKeyCount()
        {
            return data.Count;
        }

        /// <summary>
        /// 调试输出所有数据
        /// </summary>
        public void DebugPrintAll()
        {
            Debug.Log("=== Blackboard Contents ===");
            foreach (var kvp in data)
            {
                Debug.Log($"  {kvp.Key}: {kvp.Value} ({dataTypes[kvp.Key].Name})");
            }
            Debug.Log("===========================");
        }
    }
} 